package com.cloudfun.campusshare.device.protocol;


import com.aliyuncs.IAcsClient;
import com.aliyuncs.iot.model.v20180120.PubRequest;
import com.aliyuncs.iot.model.v20180120.PubResponse;
import com.cloudfun.campusshare.common.constant.Code;
import com.cloudfun.campusshare.common.exception.BusinessException;
import com.cloudfun.campusshare.device.protocol.command.Frame;
import com.cloudfun.campusshare.device.protocol.command.PumpFrame;
import com.cloudfun.campusshare.service.CommandMessageService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.internal.websocket.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Created by Huqin on 2019/12/21
 */
@Slf4j
@Component
public class AliyunIotMsgSender {

    @Autowired
    private IAcsClient client;

    @Autowired
    private CommandMessageService commandMessageService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 下发消息并锁定设备
     *
     * @param deviceType
     * @param productKey
     * @param deviceName
     * @param frame
     * @return
     */
    @Transactional
    public boolean sendAndLock(String deviceType, String productKey, String deviceName, Frame frame) {
        boolean res = this.send(deviceType, productKey, deviceName, frame);
        if (res) {
            // 加锁
            stringRedisTemplate.opsForValue().set("DEVICE_RESET" + deviceName, deviceName, 2, TimeUnit.SECONDS);
        }
        return res;
    }

    /**
     * 下发消息
     *
     * @param deviceType
     * @param deviceName
     * @param productKey
     * @param frame
     */
    @Transactional
    public boolean send(String deviceType, String productKey, String deviceName, Frame frame) {
        if (!Objects.isNull(stringRedisTemplate.opsForValue().get("DEVICE_RESET" + deviceName))) {
            throw new BusinessException(Code.ERROR, "设备忙");
        }
        // 保存
        commandMessageService.create(deviceType, deviceName, frame);
        return this.send(productKey, deviceName, frame.toString());
    }

    @Transactional
    public boolean send(String deviceType, String productKey, String deviceName, PumpFrame frame) {
        if (!Objects.isNull(stringRedisTemplate.opsForValue().get("DEVICE_RESET" + deviceName))) {
            throw new BusinessException(Code.ERROR, "设备忙");
        }
        // 保存
        commandMessageService.create(deviceType, deviceName, frame);
        return this.send(productKey, deviceName, frame.toString());
    }

    /**
     * 下发消息
     *
     * @param productKey
     * @param deviceName
     * @param msg
     * @return
     */
    public boolean send(String productKey, String deviceName, String msg) {
        return this.send(productKey, deviceName, msg, 1);
    }

    /**
     * 下发消息
     *
     * @param productKey
     * @param deviceName
     * @param msg
     * @param qos
     * @return
     */
    public boolean send(String productKey, String deviceName, String msg, int qos) {
        // 发送
        PubRequest request = new PubRequest();
        request.setQos(qos);
        //设置发布消息的topic
        String topicName = "/" + productKey + "/" + deviceName + "/user/get";
        request.setTopicFullName(topicName);
        request.setProductKey(productKey);
        //设置消息的内容，一定要用base64编码，否则乱码
        request.setMessageContent(Base64.encode(msg));
        try {
            PubResponse response = client.getAcsResponse(request);
            log.debug("pub [{}] to:{} success:{}", msg, topicName, response.getSuccess());
        } catch (Exception e) {
            log.error("向阿里云IOT平台发送消息时异常：", e);
            return false;
        }
        return true;
    }

}
